function [X,Y,Out] = lmafit_mc(m,n,k,Known,data,opts)
%
% Solver for matrix completion:
%
%        U_ij ~= A_ij,  for i,j in Known
%
% where U =  X*Y and A_ij's are given in an known index set.
%
% Output:
%           X --- m x k matrix
%           Y --- k x n matrix
%         Out --- output information
% Input:
%        m, n --- matrix sizes
%           k --- rank estimate
%        data --- values of known elements in a 1D row vector
%       Known --- positions of known elements in a 1D row vector
%                 assuming matrices are arranged column-wise
%        opts --- option structure with fields: opt, maxit
%
% Copyright(c) 2009 Yin Zhang

%% initialize
set_param;
if outobj; objv = zeros(maxit,1); end
if iprint;
    fprintf('\nLMafit_mc: Zfull = %i\n',Zfull);
    fprintf('Iteration:     '); 
end
[X,Y,Z] = MC_iter(m,n,k,Zfull,Known,data);

%% main iterations
for iter = 1:maxit

    [X,Y,Z,Res] = MC_iter(X,Y,Z,Zfull);
    res0 = res; res = norm(Res);
    reschg = abs(res0-res)/datanrm;
    if iprint; fprintf('\b\b\b\b\b%5i',iter); end
    if outobj; objv(iter) = res; end
    if reschg < tol; break; end
    
end %iter

Out.iter = iter;
if iprint; fprintf('\n'); end
if outobj; Out.obj = objv(1:iter)/datanrm; end


%% nested function %%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function set_param
        tol = 1e-4;
        maxit = 999;
        iprint = 1;
        outobj = 0;
        L = length(data);
        Zfull = L/(m*n) > 0.2 || k > .02*min(m,n) || m*n < 5e5;
        if isfield(opts,'tol');       tol = opts.tol;    end
        if isfield(opts,'maxit');   maxit = opts.maxit;  end
        if isfield(opts,'print');  iprint = opts.print;  end
        if isfield(opts,'Zfull');   Zfull = opts.Zfull;  end
        if isfield(opts,'outobj'); outobj = opts.outobj; end
        res = inf;
        datanrm = max(1,norm(data));
    end %set_param

end %main
